package com.neo.tiny.admin.service.sys.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.neo.tiny.admin.mapper.sys.SysMenuMapper;
import com.neo.tiny.admin.service.sys.SysMenuService;
import com.neo.tiny.admin.vo.menu.SysMenuVO;
import com.neo.tiny.common.constant.CommonConstants;
import com.neo.tiny.common.enums.MenuTypeEnum;
import com.neo.tiny.admin.entity.sys.SysMenu;
import com.neo.tiny.common.util.CommonDoTransfer;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: yqz
 * @CreateDate: 2022/8/7 19:26
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
    @Override
    public List<Tree<Long>> filterMenu(List<SysMenuVO> menus, Long parentId) {
        if (CollUtil.isEmpty(menus)) {
            return new ArrayList<>();
        }
        List<TreeNode<Long>> collect = menus.stream()
                .filter(menu -> MenuTypeEnum.LEFT_MENU.getType().equals(menu.getMenuType())
                        || MenuTypeEnum.DIR_MENU.getType().equals(menu.getMenuType()))
                .filter(menu -> StrUtil.isNotBlank(menu.getPath())).map(getNodeFunction()).collect(Collectors.toList());

        Long parent = parentId == null ? CommonConstants.MENU_TREE_ROOT_ID : parentId;

        return TreeUtil.build(collect, parent);
    }

    @Override
    public List<Tree<Long>> treeMenu(boolean lazy, Long parentId) {
        List<SysMenu> sysMenus = baseMapper.selectList(Wrappers.<SysMenu>lambdaQuery()
                .orderByAsc(SysMenu::getSortOrder));
        List<SysMenuVO> menuVoList = CommonDoTransfer.transfer(sysMenus, SysMenuVO.class);
        if (!lazy) {

            List<TreeNode<Long>> collect = menuVoList.stream()
                    .map(getNodeFunction()).collect(Collectors.toList());

            return TreeUtil.build(collect, CommonConstants.MENU_TREE_ROOT_ID);
        }

        Long parent = parentId == null ? CommonConstants.MENU_TREE_ROOT_ID : parentId;

        List<TreeNode<Long>> collect = menuVoList.stream()
                .map(getNodeFunction())
                .collect(Collectors.toList());

        return TreeUtil.build(collect, parent);
    }

    @NotNull
    private Function<SysMenuVO, TreeNode<Long>> getNodeFunction() {
        return menu -> {
            TreeNode<Long> node = new TreeNode<>();
            node.setId(menu.getId());
            node.setName(menu.getMenuName());
            node.setParentId(menu.getParentId());
            node.setWeight(menu.getSortOrder());
            // 扩展属性
            Map<String, Object> extra = new HashMap<>();
            extra.put("icon", menu.getIcon());
            extra.put("path", menu.getPath());
            // 配合前端配置组件和访问路径分离
            extra.put("component", menu.getComponent());
            extra.put("menuType", menu.getMenuType());
            extra.put("perms", menu.getPerms());
            extra.put("query", menu.getQuery());
            extra.put("label", menu.getMenuName());
            extra.put("sortOrder", menu.getSortOrder());
            extra.put("keepAlive", menu.getKeepAlive());
            node.setExtra(extra);
            return node;
        };
    }
}
